home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / cljul90.zip / COLORFUN.C < prev    next >
Text File  |  1990-04-18  |  17KB  |  626 lines

  1.  
  2. /*
  3.  *      colorfun.c
  4.  *      X Window demo program that draws a colored box 
  5.  *      in a window. Every second, we change the color.
  6.  *
  7.  *      To compile and run this program, you
  8.  *      will need to link in the X library
  9.  *      (usually called Xlib), usually done with
  10.  *      a command something like:
  11.  *
  12.  *              cc -o colorfun colorfun.c -lX11
  13.  *
  14.  *      (On UNIX systems.)
  15.  *
  16.  *      Note that we use some functions found only
  17.  *      in the Release 4 Xlib.  These functions are
  18.  *      marked as such, so if you have an R3 or
  19.  *      older system you can easily convert.
  20.  *
  21.  *      Written for Computer Language magazine
  22.  *      by E F Johnson and K Reichard, 1990.
  23.  *
  24.  */
  25.  
  26. #include   <stdio.h>
  27.  
  28. /*
  29.  *      Most X programs will need Xlib.h and Xutil.h
  30.  */
  31. #include   <X11/Xlib.h>
  32. #include   <X11/Xutil.h>
  33.  
  34.  
  35.  
  36. main( argc, argv )
  37.  
  38. int     argc;
  39. char    *argv[];
  40.  
  41. {       /* -- main */
  42.         Display         *display;
  43.         int             screen;
  44.         Window          window;
  45.         GC              gc;
  46.         int             done;
  47.         XColor          the_color;
  48.         Visual          *visual;
  49.         int             depth;
  50.         XFontStruct     *font;
  51.         int             status;
  52.         Colormap        colormap;
  53.         unsigned long   black, white;
  54.  
  55.  
  56.         /*
  57.          *      1) Set up X display connection with the server
  58.          *      named in the user's DISPLAY environment variable.
  59.          */
  60.         display = XOpenDisplay( NULL );
  61.  
  62.         if ( display == (Display *) NULL )
  63.                 {
  64.                 (void) fprintf( stderr, "Error: Could not open display\n" );
  65.                 exit( 1 );      
  66.                 }
  67.  
  68.  
  69.         /*
  70.          *      2) Find a visual that supports color and get its depth.
  71.          */
  72.         screen = DefaultScreen( display );
  73.  
  74.         SetUpVisual( display, screen, &visual, &depth );
  75.  
  76.  
  77.         /*
  78.          *      3a) Create Color map and get a black and white 
  79.          *      pixel values for the colormap.
  80.          */
  81.         SetUpColormap( display, screen, visual, &colormap, &black, &white );
  82.  
  83.  
  84.         /*
  85.          *      3b) Allocate one read-write color cell.
  86.          */
  87.         status = XAllocColorCells( display, colormap, 
  88.                         False, NULL, 0, &the_color.pixel, 1 );
  89.  
  90.         if ( status == 0 )
  91.                 {
  92.                 (void) fprintf( stderr, "Error in allocating color cell.\n" );
  93.                 XCloseDisplay( display );
  94.                 exit( 1 );
  95.                 }
  96.  
  97.         /*
  98.          * Set up some "random" RGB color values.
  99.          */ 
  100.         the_color.red   = ( 1   << 8 );
  101.         the_color.green = ( 104 << 8 );
  102.         the_color.blue  = ( 200 << 8 );
  103.  
  104.         /*
  105.          *      4) Load a font
  106.          */
  107.         font = XLoadQueryFont( display, "fixed" );
  108.  
  109.         if ( font == (XFontStruct *) NULL )
  110.                 {
  111.                 (void) fprintf( stderr, "Error loading fixed font\n" );
  112.                 XCloseDisplay( display );
  113.                 exit( 1 );
  114.                 }
  115.  
  116.  
  117.         /*
  118.          *      5) Create a window and set ICCCM values.
  119.          */
  120.         SetUpWindow( display, visual, depth, colormap, black, white, &window );
  121.  
  122.  
  123.         /*
  124.          *      6) Create a graphics context (GC) for our window.
  125.          */
  126.         gc = XCreateGC( display, window, 0x0, (XGCValues *) NULL );
  127.         XSetFont( display, gc, font->fid );
  128.         XSetBackground( display, gc, white );
  129.  
  130.  
  131.         /*
  132.          *      7) "Map" our window, making it appear
  133.          *      on the screen.
  134.          */
  135.         XMapRaised( display, window );
  136.         XFlush( display );
  137.  
  138.         
  139.         /*
  140.          *      8) Loop on events, exit on a ButtonPress event.
  141.          */
  142.         done = False;
  143.         while( !done )
  144.                 {
  145.                 done = CheckForEvents( display, window, gc, 
  146.                                 &the_color, black );
  147.  
  148.                 /*
  149.                  *      9) Sleep for a second,
  150.                  *      to space out the color changes.
  151.                  */
  152.                 sleep( 1 );
  153.  
  154.  
  155.                 /*
  156.                  *      10) Change the color in our window.
  157.                  */
  158.                 ChangeColor( display, colormap, &the_color );
  159.  
  160.  
  161.                 /*
  162.                  *      11) Redraw with the new color
  163.                  */
  164.                 Redraw( display, window, gc, &the_color, black );
  165.                 }
  166.         
  167.         /*
  168.          *      12) Free/Destroy our window, GC, and font.
  169.          */
  170.         XDestroyWindow( display, window );
  171.         XFreeGC( display, gc );
  172.         XFreeFont( display, font );
  173.  
  174.  
  175.         /*
  176.          *      13) Close our X display connection and quit.
  177.          */
  178.         XCloseDisplay( display );
  179.         exit( 0 );
  180.  
  181. }       /* -- main */
  182.  
  183.  
  184. CheckForEvents( display, window, gc, the_color, black )
  185.  
  186. Display         *display;
  187. Window          window;
  188. GC              gc;
  189. XColor          *the_color;
  190. unsigned long   black;
  191.  
  192.  
  193. /*
  194.  *      8) Loop on events.
  195.  *      CheckForEvents() checks to see if an X event
  196.  *      is pending.  If so, CheckForEvents() reads in
  197.  *      that event and then acts on it (perhaps by
  198.  *      doing nothing).  We ignore changes to the window's
  199.  *      size (it is assumed the user will be too 
  200.  *      dazzled by the program to even think about resizing
  201.  *      the window).
  202.  */
  203.  
  204. {       /* -- function CheckForEvents */
  205.         XEvent  event;
  206.         int     done = False;
  207.  
  208.         /*
  209.          *      8a) Do we have an event waiting?
  210.          */
  211.         if ( XPending( display ) > 0 )
  212.                 {
  213.                 XNextEvent( display, &event );
  214.  
  215.                 switch( event.type )
  216.                         {
  217.                         /*
  218.                          * 8b) Set a flag if a mouse button
  219.                          * is pressed. We will exit later.
  220.                          */
  221.                         case ButtonPress: 
  222.                                 done = True; 
  223.                                 break;
  224.  
  225.                         /*      
  226.                          * 8c) Only redraw our window when
  227.                          * the last Expose event comes in.
  228.                          */
  229.                         case Expose:
  230.                                 if ( event.xexpose.count == 0 )
  231.                                         {
  232.                                         Redraw( display, window, 
  233.                                                 gc, the_color, black );
  234.                                         }
  235.                                 break;
  236.                         }
  237.                 }
  238.  
  239.         return( done );
  240.  
  241. }       /* -- function CheckForEvents */
  242.  
  243.  
  244.  
  245. Redraw( display, window, gc, the_color, black )
  246.  
  247. Display         *display;
  248. Window          window;
  249. GC              gc;
  250. XColor          *the_color;
  251. unsigned long   black;
  252.  
  253.  
  254. /*
  255.  *      Redraw() redraws our window.  Redraw()
  256.  *      is called whenever the window's contents
  257.  *      need to be refreshed, because the contents
  258.  *      have changed, or because the window system
  259.  *      requests we redraw the window due to "damage".
  260.  */
  261.  
  262. {       /* -- function Redraw */
  263.         char    string[ 120 ];
  264.  
  265.         /*
  266.          * Fill in a rectangle, in the given color.
  267.          */
  268.         XSetForeground( display, gc, the_color->pixel );
  269.  
  270.         XFillRectangle( display, window, gc,
  271.                 10, 30, 200, 100 );
  272.  
  273.  
  274.         /*
  275.          * Draw text in black
  276.          */
  277.         XSetForeground( display, gc, black );
  278.  
  279.  
  280.         /*
  281.          * Display current color values as text
  282.          */
  283.         (void) sprintf( string, "R 0x%5.5x G 0x%5.5x B 0x%5.5x",
  284.                 the_color->red,
  285.                 the_color->green, 
  286.                 the_color->blue );
  287.  
  288.  
  289.         XDrawImageString( display, window, gc,
  290.                 10, 20,
  291.                 string, strlen( string ) );
  292.  
  293.         /*
  294.          * Send output requests to the X server
  295.          */
  296.         XFlush( display );
  297.  
  298. }       /* -- function Redraw */
  299.  
  300.  
  301.  
  302. SetUpColormap( display, screen, visual, colormap, black, white )
  303.  
  304. Display         *display;
  305. int             screen;
  306. Visual          *visual;
  307. Colormap        *colormap;
  308. unsigned long   *black, *white;
  309.  
  310. /*
  311.  *      SetUpColormap() creats an X colormap using the
  312.  *      given screen and visual.  Color cells (pixels)
  313.  *      for "black" and "white" are also allocated in
  314.  *      our new colormap.
  315.  */
  316.  
  317. {       /* -- function SetUpColormap */
  318.         int     status;
  319.         XColor  hardwarecolor, exactcolor;
  320.  
  321.  
  322.         /*
  323.          * Create a colormap using the
  324.          * visual found in SetUpVisual().
  325.          */
  326.         *colormap = XCreateColormap( display,
  327.                         RootWindow( display, screen ),
  328.                         visual,
  329.                         AllocNone );
  330.  
  331.  
  332.         /*
  333.          * Check for failure.
  334.          */
  335.         if ( *colormap != None )
  336.                 {
  337.                 /* -- Set up "white" in the new colormap */
  338.                 status = XAllocNamedColor( display, *colormap, "white",
  339.                                 &hardwarecolor,
  340.                                 &exactcolor );
  341.  
  342.                 if ( status != 0 )
  343.                         {
  344.                         *white  = hardwarecolor.pixel;
  345.  
  346.  
  347.                         /* -- Set up "black" in the new colormap */
  348.                         status = XAllocNamedColor( display, *colormap, "black",
  349.                                         &hardwarecolor,
  350.                                         &exactcolor );
  351.  
  352.                         *black  = hardwarecolor.pixel;
  353.                         }
  354.                 }
  355.         else
  356.                 {
  357.                 status = 0;
  358.                 }
  359.  
  360.         if ( status == 0 )
  361.                 {
  362.                 (void) fprintf( stderr, "Error in creating colormap\n" );
  363.                 XCloseDisplay( display );
  364.                 exit( 1 );
  365.                 }
  366.  
  367. }       /* -- function SetUpColormap */
  368.  
  369.  
  370.  
  371. SetUpVisual( display, screen, visual, depth )
  372.  
  373. Display *display;
  374. int     screen;
  375. Visual  **visual;
  376. int     *depth;
  377.  
  378. /*
  379.  *      SetUpVisual() finds a PseudoColor visual
  380.  *      on the given screen.  If none is to be found,
  381.  *      the program will terminate.  *depth is set to
  382.  *      the depth of the found visual.
  383.  */
  384.  
  385. {       /* -- function SetUpVisual */
  386.         int             number_visuals;
  387.         XVisualInfo     *visual_array, visual_template;
  388.  
  389.         /*
  390.          * We want a PseudoColor visual on this screen.
  391.          * XGetVisualInfo() will get a list of all
  392.          * the PseudoColor visuals supported on
  393.          * this screen.
  394.          */
  395.         visual_template.class  = PseudoColor;
  396.         visual_template.screen = screen;
  397.  
  398.         visual_array = XGetVisualInfo( display,
  399.                                 VisualClassMask | VisualScreenMask,
  400.                                 &visual_template,
  401.                                 &number_visuals );
  402.  
  403.         /* -- Check for success */
  404.         if ( ( number_visuals > 0 ) && ( visual_array != NULL ) )
  405.                 {
  406.                 /*
  407.                  * We're lazy, we just choose the
  408.                  * first PseudoColor visual
  409.                  */
  410.                 *visual = visual_array[0].visual;
  411.                 *depth = visual_array[0].depth;
  412.  
  413.                 XFree( visual_array );
  414.                 }
  415.         else
  416.                 {
  417.                 (void) fprintf( stderr, "Error in finding visual\n" );
  418.                 XCloseDisplay( display );
  419.                 exit( 1 );
  420.                 }
  421.  
  422. }       /* -- function SetUpVisual */
  423.  
  424.  
  425.  
  426. SetUpWindow( display, visual, depth, colormap, fore, back, window )
  427.  
  428. Display         *display;
  429. Visual          *visual;
  430. int             depth;
  431. Colormap        colormap;
  432. unsigned long   fore, back;
  433. Window          *window;
  434.  
  435. /*
  436.  *      5) Create a window.  We need to be careful here
  437.  *      to use our visual and colormap.
  438.  */
  439.  
  440. {       /* -- function SetUpWindow */
  441.         int                     x, y, width, height;
  442.         XSetWindowAttributes    attributes;
  443.         unsigned long           attribute_mask;
  444.         int                     screen;
  445.         XWMHints                *wmhints;
  446.         XSizeHints              *sizehints;
  447.  
  448.  
  449.  
  450.         /*
  451.          * 5a) Determine x, y, width, height. Normally
  452.          * in X, the user should be able to specify this
  453.          * on the UNIX command-line.  For simplicity,
  454.          * we're just using arbitrary values here.
  455.          */
  456.         x      = 10;
  457.         y      = 10;
  458.         width  = 220;
  459.         height = 140;
  460.  
  461.  
  462.         /*
  463.          * 5b) Fill in a window attributes structure.
  464.          * fore and back arer the black and white colors
  465.          * allocated in our new colormap. If we use
  466.          * the default BlackPixel() and WhitePixel(),
  467.          * we may get strange values since these
  468.          * may not have been allocated in our new
  469.          * colormap.
  470.          */
  471.         attributes.background_pixel = back;
  472.         attributes.border_pixel     = fore;
  473.         attributes.event_mask       = ExposureMask | ButtonPressMask;
  474.         attributes.colormap         = colormap;
  475.  
  476.  
  477.         attribute_mask  = CWBackPixel | CWBorderPixel | 
  478.                           CWEventMask | CWColormap;
  479.  
  480.  
  481.  
  482.         /*
  483.          * 5c)  Create window
  484.          */
  485.         screen  = DefaultScreen( display );
  486.  
  487.         *window = XCreateWindow( display, 
  488.                         RootWindow( display, screen ), /* parent window */
  489.                         x, y, width, height,
  490.                         2,              /* -- border width */
  491.                         depth,
  492.                         InputOutput,    /* -- window class */
  493.                         visual,         /* -- our visual */
  494.                         attribute_mask,
  495.                         &attributes );
  496.  
  497.  
  498.         if ( *window == (Window) None )
  499.                 {
  500.                 (void) fprintf( stderr, "Error: could not open window\n" );
  501.                 XCloseDisplay( display );
  502.                 exit( 1 );
  503.                 }
  504.  
  505.  
  506.         /*
  507.          * 5d) Store a name for the window
  508.          * with the window manager.  Note we are
  509.          * using Latin-1 names, so users in Japan
  510.          * or Arabia might want to use X's compound
  511.          * text mechanism.
  512.          */
  513.         XStoreName( display, *window, "ColorFun" );
  514.  
  515.  
  516.         /*
  517.          * 5e) Set window manager hints, R4-only functions!
  518.          */
  519.         wmhints = XAllocWMHints();
  520.  
  521.         if ( wmhints != NULL )
  522.                 {
  523.                 wmhints->initial_state = NormalState;
  524.                 wmhints->input         = True;
  525.                 wmhints->flags         = StateHint | InputHint;
  526.  
  527.                 XSetWMHints( display, *window, wmhints );
  528.  
  529.                 XFree( wmhints );
  530.                 }
  531.  
  532.  
  533.         /*
  534.          * 5f) Set Size hints, again R4-specific!
  535.          * (This also requires an R4 or ICCCM-compliant
  536.          * window manager.)
  537.          */
  538.         sizehints = XAllocSizeHints();
  539.  
  540.         if ( sizehints != NULL )
  541.                 {
  542.                 sizehints->base_width  = width;    
  543.                 sizehints->base_height = height;  
  544.  
  545.                 sizehints->flags       = PBaseSize;
  546.  
  547.                 XSetWMNormalHints( display, *window, sizehints );
  548.  
  549.                 XFree( sizehints );
  550.                 }
  551.  
  552.         
  553. }       /* -- function SetUpWindow */
  554.  
  555.  
  556.  
  557. ChangeColor( display, colormap, color )
  558.  
  559. Display         *display;
  560. Colormap        colormap;
  561. XColor          *color;
  562.  
  563. /*
  564.  *      Every second, ChangeColor() is called to
  565.  *      modify the current color we are displaying.
  566.  */
  567.  
  568. {       /* -- function ChangeColor */
  569.  
  570.  
  571.         color->flags = DoRed | DoGreen | DoBlue;
  572.  
  573.         color->red   = (unsigned short) IncrementValue( color->red, 3 );
  574.         color->green = (unsigned short) IncrementValue( color->green, 6 );
  575.         color->blue  = (unsigned short) IncrementValue( color->blue, 5  );
  576.  
  577.         XStoreColor( display, colormap, color );
  578.  
  579. }       /* -- function ChangeColor */
  580.  
  581.  
  582.  
  583. IncrementValue( value, amount )
  584.  
  585. short   value;
  586. int     amount;         /* -- add this amount to value. */
  587.  
  588. /*
  589.  *      Some common 8-plane color systems seem to just 
  590.  *      use the upper byte of the color values for
  591.  *      Red, Green and Blue (hence all the >> and << 
  592.  *      bit-shift operations).  If you don't like how
  593.  *      these colors look on your system, change 
  594.  *      IncrementValue() and ChangeColor() to do what
  595.  *      you'd like. Play around with them and have fun.
  596.  */
  597.  
  598. {       /* -- function IncrementValue */
  599.         unsigned short  new_value;
  600.  
  601.         new_value = ( value >> 8 );
  602.  
  603.         new_value += amount;
  604.  
  605.         /*
  606.          * Spend more time with brighter colors.
  607.          */
  608.         if ( new_value > 200 )
  609.                 {
  610.                 new_value--;
  611.                 }
  612.  
  613.         if ( new_value > 250 )
  614.                 {
  615.                 new_value = 0;
  616.                 }
  617.  
  618.         return( new_value << 8 );
  619.  
  620. }       /* -- function IncrementValue */
  621.  
  622. /*
  623.  *      end of file
  624.  */
  625.  
  626.